# -*- coding:utf-8 -*-
__author__ = 'Dragon Sun'
__date__ = '2025-06-24 15:20:08'

from pathlib import Path
from typing import Optional, Union

import pandas
from PySide6.QtCore import QObject
from PySide6.QtWidgets import QApplication, QFrame, QRadioButton, QGridLayout, QPushButton, QLineEdit
from dsOKXv5.data_types import 交易方向枚举
from dsOKXv5.models import 持仓模型类
from dsPyLib.utils.logging import logger
from dsPySide6.utils.func import load_ui

from src.helpers.helper_ui import 显示错误对话框
from src.views.交易视图.交易视图控制器 import 交易视图控制器类, 值守平仓方式枚举


class DemoViewController(QObject):

    # noinspection PyUnresolvedReferences
    def __init__(self):
        super().__init__()

        # 视图
        UI文件名 = Path(__file__).resolve().parent / 'demo.ui'
        self.视图 = load_ui(ui_file=UI文件名, custom_widgets=[], parent=None)

        # 组件映射
        self._容器: QFrame = self.视图.frame
        self._容器布局: QGridLayout = self.视图.frameLayout
        self._传递K线按钮: QPushButton = self.视图.btnKLine
        self._清除K线按钮: QPushButton = self.视图.btnClearKLine
        self._最大下单量文本框: QLineEdit = self.视图.edtMaxVol
        self._传递最大下单量按钮: QPushButton = self.视图.btnMaxVol
        self._有持仓单选框: QRadioButton = self.视图.rbPos
        self._无持仓单选框: QRadioButton = self.视图.rbNoPos
        self._开多单选框: QRadioButton = self.视图.rbLong
        self._开空单选框: QRadioButton = self.视图.rbShort
        self._吃单成功单选框: QRadioButton = self.视图.rbTakerTrue
        self._吃单失败单选框: QRadioButton = self.视图.rbTakerFalse
        self._市价全平成功单选框: QRadioButton = self.视图.rbClosePositionTrue
        self._市价全平失败单选框: QRadioButton = self.视图.rbClosePositionFalse
        self._反手成功单选框: QRadioButton = self.视图.rbReverseTrue
        self._反手失败单选框: QRadioButton = self.视图.rbReverseFalse
        self._设置止损成功单选框: QRadioButton = self.视图.rbStopLossTrue
        self._设置止损失败单选框: QRadioButton = self.视图.rbStopLossFalse
        self._设置止盈成功单选框: QRadioButton = self.视图.rbTakeProfitTrue
        self._设置止盈失败单选框: QRadioButton = self.视图.rbTakeProfitFalse
        self._自动值守成功单选框: QRadioButton = self.视图.rbAutoClosePositionTrue
        self._自动值守失败单选框: QRadioButton = self.视图.rbAutoClosePositionFalse

        # 组件事件
        self._传递K线按钮.clicked.connect(self._传递K线按钮处理)
        self._清除K线按钮.clicked.connect(self._清除K线按钮处理)
        self._传递最大下单量按钮.clicked.connect(self._传递最大下单量处理)
        self._有持仓单选框.toggled.connect(self._持仓单选框处理)
        self._无持仓单选框.toggled.connect(self._持仓单选框处理)

        # 设置初始属性
        self._容器.setStyleSheet('')

        # 添加交易视图
        self._交易视图控制器 = 交易视图控制器类()
        self._容器布局.addWidget(self._交易视图控制器.视图)

        # 交易视图控制器回调
        self._交易视图控制器.吃单处理 = self._回调_吃单
        self._交易视图控制器.市价全平处理 = self._回调_市价全平
        self._交易视图控制器.反手处理 = self._回调_反手
        self._交易视图控制器.设置止损处理 = self._回调_设置止损
        self._交易视图控制器.设置止盈处理 = self._回调_设置止盈
        self._交易视图控制器.自动值守处理 = self._回调_自动值守

        # 传递K线
        # self._传递K线按钮处理()

    # -------------------- 回调处理 -------------------- #

    def _回调_吃单(self, 交易方向: 交易方向枚举, 交易数量: float) -> Union[Optional[持仓模型类], Exception]:
        返回状态 = self._吃单成功单选框.isChecked()
        logger.info(f'吃单：交易方向={交易方向.name}, 交易数量={交易数量}, {返回状态}')

        if 返回状态:
            # 更改方向单选框显示
            if 交易方向 == 交易方向枚举.多:
                self._开多单选框.setChecked(True)
            else:
                self._开空单选框.setChecked(True)

            # 更改持仓单选框显示
            self._有持仓单选框.setChecked(True)  # 外部更新交易视图持仓状态

            return 持仓模型类()
        else:
            e = ValueError('Test:失败了！')
            显示错误对话框(信息=str(e))
            return e

    def _回调_市价全平(self) -> Optional[Exception]:
        返回状态 = self._市价全平成功单选框.isChecked()
        logger.info(f'市价全平, {返回状态}')

        if 返回状态:
            self._无持仓单选框.setChecked(True)  # 更新持仓单选框显示
            self._交易视图控制器.传递持仓(持仓=None)
            return None
        else:
            e = ValueError('Test:失败了！')
            显示错误对话框(信息=str(e))
            return e

    def _回调_反手(self) -> Union[Optional[持仓模型类], Exception]:
        返回状态 = self._反手成功单选框.isChecked()
        logger.info(f'反手, {返回状态}')

        # 如果成功，更新持仓状态
        if 返回状态:
            # 外部更新交易视图持仓状态
            方向 = 交易方向枚举.空 if self._开多单选框.isChecked() else 交易方向枚举.多
            持仓 = 持仓模型类(方向=方向)
            self._交易视图控制器.传递持仓(持仓=持仓)

            # 更改方向单选框显示
            if 方向 == 交易方向枚举.多:
                self._开多单选框.setChecked(True)
            else:
                self._开空单选框.setChecked(True)

            return 持仓
        else:
            e = ValueError('Test:失败了！')
            显示错误对话框(信息=str(e))
            return e

    def _回调_设置止损(self, 止损触发价: float) -> Union[Optional[持仓模型类], Exception]:
        返回状态 = self._设置止损成功单选框.isChecked()
        logger.info(f'设置止损：止损价={止损触发价}, {返回状态}')
        logger.info(f'{type(止损触发价)}')

        if 返回状态:
            # 外部更新交易视图持仓状态
            方向 = 交易方向枚举.多 if self._开多单选框.isChecked() else 交易方向枚举.空
            持仓 = 持仓模型类(方向=方向)
            self._交易视图控制器.传递持仓(持仓=持仓)
            return 持仓
        else:
            e = ValueError('Test:失败了！(这里假设止损触发价和最新价格的关系错误)')
            显示错误对话框(信息=str(e))
            return e

    def _回调_设置止盈(self, 止盈触发价: float) -> Union[Optional[持仓模型类], Exception]:
        返回状态 = self._设置止盈成功单选框.isChecked()
        logger.info(f'设置止盈：止盈价={止盈触发价}, {返回状态}')
        logger.info(f'{type(止盈触发价)}')

        if 返回状态:
            # 外部更新交易视图持仓状态
            方向 = 交易方向枚举.多 if self._开多单选框.isChecked() else 交易方向枚举.空
            持仓 = 持仓模型类(方向=方向)
            self._交易视图控制器.传递持仓(持仓=持仓)

            return 持仓
        else:
            e = ValueError('Test:失败了！(这里假设止损触发价和最新价格的关系错误)')
            显示错误对话框(信息=str(e))
            return e

    def _回调_自动值守(self, 值守状态: bool, 平仓方式: set[值守平仓方式枚举]) -> Optional[Exception]:
        返回状态 = self._自动值守成功单选框.isChecked()
        logger.info(f'自动值守：值守状态={值守状态}, 平仓方式={平仓方式}, {返回状态}')

        if 返回状态:
            return None
        else:
            e = ValueError('Test:失败了！')
            显示错误对话框(信息=str(e))
            return e

    # -------------------- 事件处理 -------------------- #

    def _持仓单选框处理(self, checked: bool):
        if not checked:
            return

        sender = self.sender()
        if sender == self._有持仓单选框:
            持仓方向 = 交易方向枚举.多 if self._开多单选框.isChecked() else 交易方向枚举.空
            持仓 = 持仓模型类(方向=持仓方向)
            self._交易视图控制器.传递持仓(持仓=持仓)
        else:
            self._交易视图控制器.传递持仓(持仓=None)

    def _传递K线按钮处理(self):
        # 传递近期K线和持仓状态
        K线文件名 = Path(__file__).resolve().parent / 'demo_K线.csv'
        K线 = pandas.read_csv(K线文件名)
        K线 = K线.tail(n=self._交易视图控制器.K线最大数量)
        K线['时间槽'] = pandas.to_datetime(K线['时间槽'])
        self._交易视图控制器.传递近期K线(K线=K线)

    def _清除K线按钮处理(self):
        self._交易视图控制器.传递近期K线(K线=None)

    def _传递最大下单量处理(self):
        try:
            最大下单量 = float(self._最大下单量文本框.text())
        except ValueError:
            显示错误对话框(信息='最大下单量输入错误')
            return

        self._交易视图控制器.传递最大下单量(最大下单量=最大下单量)


if __name__ == '__main__':
    app = QApplication()
    app.setQuitOnLastWindowClosed(True)
    vc = DemoViewController()
    vc.视图.show()
    app.exec()
